<template>
  <div class="demo-block" :class="[target?'ab':'']" :id="cref">
    <div class="pug-calendar">
      <div class="pug-calendar__header">
        <div class="pug-calendar__title">
          {{ year }} 年 {{ month + 1 }} 月
        </div>
        <div class="pug-calendar__button-group">
          <div class="pug-button-group">
            <button type="button" @click.prevent="prevMonth" class="pug-button pug-button--plain pug-button--mini"><!---->
              <!----><span>
          上个月
        </span></button>
            <button @click.prevent="todayMonth" type="button" class="pug-button pug-button--plain pug-button--mini"><!---->
              <!----><span>
          今天
        </span></button>
            <button @click.prevent="nextMonth" type="button" class="pug-button pug-button--plain pug-button--mini"><!---->
              <!----><span>
          下个月
        </span></button>
          </div>
        </div>
      </div>
      <div class="pug-calendar__body">
        <table cellspacing="0" cellpadding="0" class="pug-calendar-table">
          <thead>
          <th v-for="week in weeks">{{ week }}</th>
          </thead>
          <tbody>
          <tr class="pug-calendar-table__row" v-for="(dateitem,index) in dateArr" :key="index">
            <td :title="date.full" class="current" :class="[date.prev?'prev':'',date.next?'next':'']"
                v-for="(date,cindex) in dateitem"
                :key="cindex">

              <div v-if="pnevent">
                <div v-if="!date.next && !date.prev" @click="selectDate(index,cindex)" class="pug-calendar-day"
                     :class="[date.days == days ? 'active':'']">
                  <span>{{ date.days === 0 ? '' : date.days }}</span></div>
                <div v-if="date.next && !date.prev" @click="nextMonth()" class="pug-calendar-day"
                     :class="[date.days == days ? 'active':'']">
                  <span>{{ date.days === 0 ? '' : date.days }}</span></div>
                <div v-if="!date.next && date.prev" @click="prevMonth()" class="pug-calendar-day"
                     :class="[date.days == days ? 'active':'']">
                  <span>{{ date.days === 0 ? '' : date.days }}</span></div>
              </div>
              <div v-else>
                <div @click="selectDate(index,cindex)" class="pug-calendar-day"
                     :class="[date.days == days ? 'active':'']">
                  <span>{{ date.days === 0 ? '' : date.days }}</span></div>
              </div>
            </td>
          </tr>
          </tbody>
        </table>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "time",
  data() {
    return {
      year: 1997,
      month: 1,
      days: 1,
      weeks: [],
      pnevent: true,
      pattern: "yyyy-MM-dd",
      dateArr: []
    }
  },

  props: {
    modelValue: String,
    cref:{
      type:String,
      default:""
    },
    target: String,
    pnactive: {
      type: Boolean,
      default: true
    },
    weekarr: {
      type: Array,
      default: ['日', '一', '二', '三', '四', '五', '六']
    },

    fmt: {
      type: String,
      default: "yyyy-MM-dd"
    }

  },

  created() {
    this.pattern = this.$props.fmt;
    this.weeks = this.$props.weekarr;
    this.pnevent = this.$props.pnactive;
    const date = new Date();
    this.year = date.getFullYear();
    this.month = date.getMonth();
    this.days = date.getDate();
    this.query();
  },

  methods: {
    nextMonth() {
      const dt = new Date(this.year, this.month, 1);
      const nextDate = this.getDateOfNextMonth(dt);
      this.year = nextDate.getFullYear();
      this.month = nextDate.getMonth();
      this.query();
    },

    todayMonth() {
      const currentDate = new Date();
      this.year = currentDate.getFullYear();
      this.month = currentDate.getMonth();
      this.query();
    },

    prevMonth() {
      const dt = new Date(this.year, this.month, 1);
      const prevDate = this.getDateOfPreMonth(dt);
      this.year = prevDate.getFullYear();
      this.month = prevDate.getMonth();
      this.query();
    },

    query() {
      var year = this.year;
      var month = this.month
      var arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
      if (year) {
        // 获取月份的第一天
        var firstDate = new Date(year, month, 1);
        // 第一天对应是周几
        var dayOfWeek = firstDate.getDay();
        // 该月份有多少天
        var conutDay = this.getMonthDays(year, month);

        this.eachFor(1, conutDay, (val) => {
          arr[dayOfWeek + val - 1] = {
            year,
            month: month + 1,
            days: val,
            full: this.dateToString(year, month, val),
            next: false,
            prev: false
          };
        });

        this.dateArr = this.splitArray(arr, 7);
        this.overbuqi(arr, firstDate);

      } else {
        alert('请先选择年份和月份');
      }
    },

    overbuqi(arr, firstDate) {
      // 补齐首位
      var prevDate = this.getDateOfPreMonth(firstDate);
      var prevDays = this.getMonthDays(prevDate.getFullYear(), prevDate.getMonth());
      var fzerocount = this.dateArr[0].filter(item => item === 0).length;
      this.dateArr[0] = this.dateArr[0].map((item) => {
        if (item === 0) {
          fzerocount--;
          var obj = {
            year: prevDate.getFullYear(),
            month: prevDate.getMonth() + 1,
            full: this.dateToString(prevDate.getFullYear(), prevDate.getMonth(), prevDays - fzerocount),
            days: prevDays - fzerocount,
            prev: true,
            next: false
          };
          return obj;
        }
        return item;
      })


      var zerocountf = this.dateArr[4].filter(item => item === 0).length;
      var zerocountff = this.dateArr[5].filter(item => item === 0).length;
      var zerocount = zerocountf + zerocountff;
      if (zerocount > 7) {
        this.dateArr.pop();
      }

      // 开始补齐尾号
      var nextcount = 1;
      var nextDate = this.getDateOfNextMonth(firstDate);
      if (this.dateArr.length == 5) {
        this.dateArr[4] = this.dateArr[4].map(item => {
          if (item === 0) {
            var days = nextcount++;
            var obj = {
              year: nextDate.getFullYear(),
              month: nextDate.getMonth() + 1,
              full: this.dateToString(nextDate.getFullYear(), nextDate.getMonth(), days),
              days: days,
              next: true,
              prev: false
            };
            return obj;
          }
          return item;
        })
      }

      if (this.dateArr.length == 6) {
        this.dateArr[5] = this.dateArr[5].map(item => {
          if (item === 0) {
            var days = nextcount++;
            var obj = {
              year: nextDate.getFullYear(),
              month: nextDate.getMonth() + 1,
              full: this.dateToString(nextDate.getFullYear(), nextDate.getMonth(), days),
              days: days,
              next: true,
              prev: false
            };
            return obj;
          }
          return item;
        })
      }
    },

    strToDate(year, month, days) {
      return new Date(year, month, days);
    },

    strToDateLine(datetime) {
      return typeof datetime == "string" ? new Date(datetime.replace(/-/ig, "/")) : datetime;
    },

    dateToString(year, month, days) {
      var date = this.strToDate(year, month, days);
      return this.format(date, this.pattern);
    },

    dateToStringLine(datetime) {
      return this.format(typeof datetime == "string" ? this.strToDateLine(datetime) : datetime, this.pattern);
    },


    selectDate(index, cindex) {
      const selectItem = this.dateArr[index][cindex];

      if (this.pattern == 'yyyy-MM-dd HH:mm:ss') {
        var dt = new Date();
        var fdate = new Date(selectItem.year, selectItem.month, selectItem.days, dt.getHours(), dt.getMinutes(), dt.getSeconds());
        selectItem.full = this.dateToStringLine(fdate);
      }

      this.$emit("callback", selectItem);
      this.$emit("update:modelValue", selectItem.full);
    },

    /**
     * 对Date的扩展，将 Date 转化为指定格式的String
     * 月(M)、日(d)、12小时(h)、24小时(H)、分(m)、秒(s)、周(E)、季度(q) 可以用 1-2 个占位符
     * 年(y)可以用 1-4 个占位符，毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
     * eg:
     * (new Date()).pattern("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423
     * (new Date()).pattern("yyyy-MM-dd E HH:mm:ss") ==> 2009-03-10 二 20:09:04
     * (new Date()).pattern("yyyy-MM-dd EE hh:mm:ss") ==> 2009-03-10 周二 08:09:04
     * (new Date()).pattern("yyyy-MM-dd EEE hh:mm:ss") ==> 2009-03-10 星期二 08:09:04
     * (new Date()).pattern("yyyy-M-d h:m:s.S") ==> 2006-7-2 8:9:4.18
     *
     * var date = new Date();
     * window.alert(date.pattern("yyyy-MM-dd hh:mm:ss"));
     */
    format(date, fmt) {
      var o = {
        "M+": date.getMonth() + 1, //月份
        "d+": date.getDate(), //日
        "h+": date.getHours() % 12 == 0 ? 12 : date.getHours() % 12, //小时
        "H+": date.getHours(), //小时
        "m+": date.getMinutes(), //分
        "s+": date.getSeconds(), //秒
        "q+": Math.floor((date.getMonth() + 3) / 3), //季度
        "S": date.getMilliseconds() //毫秒
      };
      var week = {
        "0": "/u65e5",
        "1": "/u4e00",
        "2": "/u4e8c",
        "3": "/u4e09",
        "4": "/u56db",
        "5": "/u4e94",
        "6": "/u516d"
      };
      if (/(y+)/.test(fmt)) {
        fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
      }
      if (/(E+)/.test(fmt)) {
        fmt = fmt.replace(RegExp.$1, ((RegExp.$1.length > 1) ? (RegExp.$1.length > 2 ? "/u661f/u671f" : "/u5468") : "") + week[this.getDay() + ""]);
      }
      for (var k in o) {
        if (new RegExp("(" + k + ")").test(fmt)) {
          fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
        }
      }
      return fmt;
    },

    eachFor(start, end, callback) {
      for (var i = start; i <= end; i++) {
        callback(i);
      }
    },

    // 分割数组
    splitArray(arr, n) {
      let res = [];
      let len = arr.length;
      let lineNum = len % n === 0 ? len / n : Math.floor((len / n) + 1);
      for (let i = 0; i < lineNum; i++) {
        let temp = arr.slice(i * n, i * n + n);
        res.push(temp);
      }
      return res;
    },

    // 是否为闰年 整百年份必须被400整除 非整百年份被4整除就都是闰年
    getMonthDays(year, month) {
      if (typeof year == 'undefined') {
        year = (new Date()).getFullYear();
      }
      if (typeof month == 'undefined') {
        month = (new Date()).getMonth();
      }
      var Feb = (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) ? 29 : 28;
      var aM = new Array(31, Feb, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
      return aM[month];
    },

    // 上一个月
    getDateOfPreMonth(dt) {
      if (typeof dt == 'undefined') {
        dt = (new Date());
      }
      var y = (dt.getMonth() == 0) ? (dt.getFullYear() - 1) : dt.getFullYear();
      var m = (dt.getMonth() == 0) ? 11 : dt.getMonth() - 1;
      var preM = this.getMonthDays(y, m);
      var d = (preM < dt.getDate()) ? preM : dt.getDate();
      return new Date(y, m, d);
    },

    // 下一个月
    getDateOfNextMonth(dt) {
      if (typeof dt == 'undefined') {
        dt = (new Date());
      }
      var y = (dt.getMonth() == 11) ? (dt.getFullYear() + 1) : dt.getFullYear();
      var m = (dt.getMonth() == 11) ? 0 : dt.getMonth() + 1;
      var preM = this.getMonthDays(y, m);
      var d = (preM < dt.getDate()) ? preM : dt.getDate();
      return new Date(y, m, d);
    }
  }

}
</script>

<style scoped>

.demo-block.ab {
  position: absolute;
  top: 34px;
  left: 0;
  z-index: 1;
}

.demo-block {
  border: 1px solid #ebebeb;
  border-radius: 3px;
  transition: .2s;
  margin-top: 1px;
  background: #fff;
}


.demo-block .source {
  padding: 24px;
}

.pug-calendar__header {
  display: flex;
  justify-content: space-between;
  padding: 12px 20px;
  border-bottom: 1px solid #ebeef5
}

.pug-calendar__title {
  color: #000;
  align-self: center
}

.pug-calendar__body {
  padding: 12px 20px 35px
}

.pug-calendar-table {
  table-layout: fixed;
  width: 100%
}

.pug-calendar-table thead th {
  padding: 12px 0;
  color: #606266;
  font-weight: 400
}

.pug-calendar-table:not(.is-range) td.next, .pug-calendar-table:not(.is-range) td.prev {
  color: #c0c4cc;
  background: #f8f8f8;
}

.pug-calendar-table td {
  border-bottom: 1px solid #ebeef5;
  border-right: 1px solid #ebeef5;
  vertical-align: top;
  transition: background-color .2s ease
}

.pug-calendar-table td.is-selected {
  background-color: #f2f8fe
}

.pug-calendar-table td.is-today {
  color: #409eff
}

.pug-calendar-table tr:first-child td {
  border-top: 1px solid #ebeef5
}

.pug-calendar-table tr td:first-child {
  border-left: 1px solid #ebeef5
}

.pug-calendar-table tr.pug-calendar-table__row--hide-border td {
  border-top: none
}

.pug-calendar-table .pug-calendar-day {
  box-sizing: border-box;
  padding: 8px;
  max-height: 85px
}

.pug-calendar-table .pug-calendar-day:hover {
  cursor: pointer;
  background-color: #f2f8fe
}


.pug-calendar-table .pug-calendar-day.active {
  cursor: pointer;
  background-color: #f2f8fe
}

</style>
